package air.jason.com.porterduffxfermodetest.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;

import air.jason.com.porterduffxfermodetest.bo.PorterDuffBO;

/**
 * @DESC:   PorterDuff模式常量
 * @Author: Jason
 * @Date: 16/8/23
 * @Time: 22:50
 */

/**
 *      PorterDuff.Mode.ADD:
 *          计算方式：Saturate(S + D)；饱和相加 ADD模式简单来说就是对图像饱和度进行相加
 *
 *      PorterDuff.Mode.CLEAR
 *          计算方式[0, 0] 清除
 *
 *      PorterDuff.Mode.DARKEN
 *          计算方式：[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]  变暗
 *          这个模式计算方式目测很复杂，其实效果很好理解，两个图像混合，
 *          较深的颜色总是会覆盖较浅的颜色，如果两者深浅相同则混合
 *
 *      PorterDuff.Mode.DST
 *          计算方式：[Da, Dc]；只绘制目标图像
 *
 *      PorterDuff.Mode.DST_ATOP
 *          计算方式：[Sa, Sa * Dc + Sc * (1 - Da)]
 *          在源图像和目标图像相交的地方绘制目标图像而在不相交的地方绘制源图像
 *
 *      PorterDuff.Mode.DST_IN
 *          计算方式：[Sa * Da, Sa * Dc]  ：只在源图像和目标图像相交的地方绘制目标图像
 *          最常见的应用就是蒙板绘制
 *
 *      PorterDuff.Mode.DST_OUT
 *          计算方式：[Da * (1 - Sa), Dc * (1 - Sa)]
 *          只在源图像和目标图像不相交的地方绘制目标图像
 *
 *      PorterDuff.Mode.DST_OVER
 *          计算方式：[Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc]；
 *          在源图像的上方绘制目标图像
 *
 *      PorterDuff.Mode.LIGHTEN
 *          计算方式：[Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]；
 *          变亮
 *
 *      PorterDuff.Mode.MULTIPLY
 *          计算方式：[Sa * Da, Sc * Dc]；：正片叠底
 *          源图像素颜色值乘以目标图像素颜色值除以255即得混合后图像像素的颜色值，该模式在设计领域应用广泛，
 *          因为其特性黑色与任何颜色混合都会得黑色，在手绘的上色、三维动画的UV贴图绘制都有应用
 *
 *      PorterDuff.Mode.OVERLAY
 *          这个模式没有在官方的API DEMO中给出，谷歌也没有给出其计算方式，
 *          在实际效果中其对亮色和暗色不起作用，也就是说黑白色无效，它会将源色与目标色混合产生一种中间色，
 *          这种中间色生成的规律也很简单，如果源色比目标色暗，那么让目标色的颜色倍增否则颜色递减。
 *
 *      PorterDuff.Mode.SCREEN
 *          计算方式：[Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] ：滤色
 *
 *      PorterDuff.Mode.SRC
 *          计算方式：[Sa, Sc]；：显示源图
 *          只绘制源图，SRC类的模式跟DIS的其实差不多
 *
 *      PorterDuff.Mode.SRC_ATOP
 *          计算方式：[Da, Sc * Da + (1 - Sa) * Dc]；
 *          ：在源图像和目标图像相交的地方绘制源图像，在不相交的地方绘制目标图像
 *
 *      PorterDuff.Mode.SRC_IN
 *          计算方式：[Sa * Da, Sc * Da]；
 *          ：只在源图像和目标图像相交的地方绘制源图像
 *
 *      PorterDuff.Mode.SRC_OUT
 *          计算方式：[Sa * (1 - Da), Sc * (1 - Da)]
 *          ：只在源图像和目标图像不相交的地方绘制源图像
 *
 *      PorterDuff.Mode.SRC_OVER
 *          计算方式：[Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc]；
 *          ：在目标图像的顶部绘制源图像
 *
 *      PorterDuff.Mode.XOR
 *          计算方式：[Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]；
 *          ：在源图像和目标图像重叠之外的任何地方绘制他们，而在不重叠的地方不绘制任何内容
 *
 *
 *
 */


public class PorterDuffXfermode1 extends View {


    private static final PorterDuff.Mode MODE = PorterDuff.Mode.DST;
    private static final int RECT_SIZE_SMALL = 400; // 左右上方示例渐变正方形的尺寸大小
    private static final int RECT_SIZE_BIG = 800; // 中间测试渐变正方形的尺寸大小

    private Paint mPaint; // 画笔
    private PorterDuffBO mPorterDuffBO;
    private PorterDuffXfermode mPorterDuffXfermode; // 图形混合模式

    private int screenW, screenH; // 屏幕尺寸
    private int s_l, s_t; // 左上方正方形的原点坐标
    private int d_l, d_t; // 右上方正方形的原点坐标
    private int rectX, rectY; // 中间正方形的原点坐标


    public PorterDuffXfermode1(Context context) {
        this(context, null);
    }

    public PorterDuffXfermode1(Context context, AttributeSet attrs) {
        super(context, attrs);

        // 实例化画笔
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

        mPorterDuffBO = new PorterDuffBO();
        // 实例化模式
        mPorterDuffXfermode = new PorterDuffXfermode(MODE);

        calu(context);

    }

    /**
     * 计算坐标
     * @param context
     */
    private void calu(Context context) {
        // 获取屏幕尺寸
        screenW = context.getResources().getDisplayMetrics().widthPixels;
        screenH = context.getResources().getDisplayMetrics().heightPixels;

        // 计算左上方正方形原点坐标
        s_l = 0;
        s_t = 0;

        // 计算右上方正方形原点坐标
        d_l = screenW - RECT_SIZE_SMALL;
        d_t = 0;

        // 计算中间正方形原点坐标
        rectX = screenW / 2 - RECT_SIZE_BIG / 2;
        rectY = RECT_SIZE_SMALL + (screenH - RECT_SIZE_SMALL) / 2 - RECT_SIZE_BIG / 2;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 设置画布颜色为黑色
        canvas.drawColor(Color.BLACK);

        // 设置业务对象尺寸值计算生成左右上方的渐变方形
        mPorterDuffBO.setSize(RECT_SIZE_SMALL);

        // 画出左右上方两个正方形  其中左边的为src 右边的为dis
        canvas.drawBitmap(mPorterDuffBO.initSrcBitmap(), s_l, s_t, mPaint);
        canvas.drawBitmap(mPorterDuffBO.initDisBitmap(), d_l, d_t, mPaint);

        // 将绘制操作保存到新的图层(更官方的说法应该是离屏缓存)
        int sc = canvas.saveLayer(0, 0, screenW, screenH,null, Canvas.ALL_SAVE_FLAG);

        // 重新设置业务对象尺寸值计算生成中间的渐变方形
        mPorterDuffBO.setSize(RECT_SIZE_BIG);

        // 先绘制dis目标图
        canvas.drawBitmap(mPorterDuffBO.initDisBitmap(), rectX, rectY, mPaint);

        // 设置混合模式
        mPaint.setXfermode(mPorterDuffXfermode);

        // 再绘制src源图
        canvas.drawBitmap(mPorterDuffBO.initSrcBitmap(), rectX, rectY, mPaint);

        // 还原混合模式
        mPaint.setXfermode(null);

        // 还原画布
        canvas.restoreToCount(sc);


    }
}
